/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ola_pal_time.h"
#include "lwip/opt.h"
#include "lwip/sntp.h"
#include "lwip/err.h"
#include "securec.h"
#include "ola_pal_os.h"
#include "cmsis_os2.h"

#define OLA_PAL_SNTP_SERVER "ntp1.aliyun.com", "cn.pool.ntp.org"
#define OLA_SNTP_DIFFERENCE_TIME 2208988800
static OlaTimeSyncAsynCallbak g_timeSyncCb = NULL;
static const char *g_sntpServer[] = {OLA_PAL_SNTP_SERVER};

static void StartSntp(void)
{
    struct timeval time;
    (void)memset_s(&time, sizeof(time), 0, sizeof(time));

    unsigned long long tempTime = 0;
    if (g_timeSyncCb != NULL) {
        int err = lwip_sntp_start(sizeof(g_sntpServer)/sizeof(g_sntpServer[0]), (char **)g_sntpServer, &time);
        sntp_stop();

        // nstp是1900年1月1日0点0分0秒开始计算的，而ola是1970年1月1日0点0分0秒开始的，所以要减去差值2208988800
        if (err == ERR_OK && (unsigned long)time.tv_sec > OLA_SNTP_DIFFERENCE_TIME) {
            tempTime += (unsigned long)time.tv_sec;
            g_timeSyncCb(tempTime - OLA_SNTP_DIFFERENCE_TIME);
        } else {
            g_timeSyncCb(tempTime);
        }
    }
}

/*
 * 功能: 尝试获取UNIX时间戳
 * 参数: timestamp，出参，获取到的UNIX时间戳
 * 返回: OLA_TIME_SYNC_FAILED，表示时间同步失败
 *       OLA_TIME_SYNC_OK，表示同步成功，同时返回有效的UNIX时间戳
 *       OLA_TIME_SYNC_ASYN，时间异步处理，并在时间同步成功后通过OlaPalTimeInit注册的回调函数返回UNIX时间戳
 * 注意: OLA SDK会在设备联网后调用该接口尝试同步时间，该接口实现请勿阻塞
 */
int OlaTimeSync(unsigned long long *timestamp, OlaTimeSyncAsynCallbak cb)
{
    if (cb == NULL) {
        return OLA_TIME_SYNC_FAILED;
    }
    g_timeSyncCb = cb;
    OlaTaskParam taskParam = {
        .taskName = "ola_time_sync",
        .level = osPriorityNormal,
        .stackSize = 2048,
    };
    OlaTask task = OlaTaskCreate(StartSntp, NULL, &taskParam);
    if (task == NULL) {
        return OLA_TIME_SYNC_FAILED;
    }
    return OLA_TIME_SYNC_ASYN;
}
